/*
 * Copyright 2011 Angel Sanadinov
 *
 * This file is part of VBox WMI.
 *
 * VBox WMI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * VBox WMI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VBox WMI.  If not, see <http://www.gnu.org/licenses/>.
 */

package Beans.Responses.DataRetrievalComponents;

import Utilities.Functions;
import Utilities.Interfaces.SelfValidating;
import com.sun.xml.ws.commons.virtualbox_3_2.IMediumAttachment;
import com.sun.xml.ws.commons.virtualbox_3_2.IStorageController;
import java.io.Serializable;
import org.virtualbox_3_2.DeviceType;
import org.virtualbox_3_2.StorageBus;
import org.virtualbox_3_2.StorageControllerType;

/**
 * This class represents machine storage data, when retrieved from the system.
 *
 * @author Angel Sanadinov
 */
public class MachineStorageData extends DataRetrievalComponent
{
    StorageControllerSettings[] controllers;     //controllers settings
    MediumAttachmentSettings[] mediumAttachments;//medium attachments settings

    /**
     * Constructs a machine storage data component using the specified data.
     *
     * @param controllers the machine's controllers
     * @param attachments the machine's media attachments
     */
    public MachineStorageData(IStorageController[] controllers, IMediumAttachment[] attachments)
    {
        if(controllers != null && attachments != null)
        {
            this.controllers = new StorageControllerSettings[controllers.length];
            this.mediumAttachments = new MediumAttachmentSettings[attachments.length];

            for(int i = 0; i < controllers.length; i++)
                this.controllers[i] = new StorageControllerSettings(controllers[i]);

            for(int i = 0; i < attachments.length; i++)
                this.mediumAttachments[i] = new MediumAttachmentSettings(attachments[i]);
        }
        else
        {
            this.controllers = null;
            this.mediumAttachments = null;
        }
    }

    /**
     * Retrieves the storage controllers data.
     *
     * @return the controllers data
     */
    public StorageControllerSettings[] getControllers()
    {
        return controllers;
    }

    /**
     * Retrieves the medium attachments data.
     *
     * @return the attachments data
     */
    public MediumAttachmentSettings[] getMediumAttachments()
    {
        return mediumAttachments;
    }

    /**
     * Checks if the controllers are valid.
     *
     * @return <code>true</code> if the controllers are valid or <code>false</code>
     *         if they are not
     */
    private boolean areControllersValid()
    {
        if(controllers != null)
        {
            for(StorageControllerSettings storageControllerSettings : controllers)
            {
                if(!storageControllerSettings.isValid())
                    return false;
                else
                    ;
            }
        }
        else
            ;

        return true;
    }

    /**
     * Checks if the media attachments are valid.
     *
     * @return <code>true</code> if the attachments are valid or <code>false</code>
     *         if they are not
     */
    private boolean areAttachmentsValid()
    {
        if(mediumAttachments != null)
        {
            for(MediumAttachmentSettings mediumAttachmentSettings : mediumAttachments)
            {
                if(!mediumAttachmentSettings.isValid())
                    return false;
                else
                    ;
            }
        }
        else
            ;

        return true;
    }

    @Override
    public boolean isValid()
    {
        if(areControllersValid() && areAttachmentsValid())
            return true;
        else
            return false;
    }

    /**
     * This class represents storage controller settings.
     */
    public class StorageControllerSettings implements Serializable, SelfValidating
    {
        private String controllerName;  //name of the controller
        private int maxDevicesPerPort;  //maximum number of devices per port
        private int lowPort;            //lowest usable port
        private int highPort;           //highest usable port
        private int vmInstanceNumber;   //controller instance number in the VM
        private int numberOfCurrentlyUsablePorts;//number of currently usable ports
        private StorageBus connectionType;//controller connection type
        private StorageControllerType controllerType;//controller type
        private boolean hostIOCacheUsed;//is the host I/O cache used

        /**
         * Constructs a storage controller object using the specified data.
         *
         * @param controller the machine's storage controller
         */
        public StorageControllerSettings(IStorageController controller)
        {
            this.controllerName = controller.getName();
            this.maxDevicesPerPort = controller.getMaxDevicesPerPortCount().intValue();
            this.lowPort = controller.getMinPortCount().intValue();
            this.highPort = controller.getMaxPortCount().intValue();
            this.vmInstanceNumber = controller.getInstance().intValue();
            this.numberOfCurrentlyUsablePorts = controller.getPortCount().intValue();
            this.connectionType = controller.getBus();
            this.controllerType = controller.getControllerType();
            this.hostIOCacheUsed = controller.getUseHostIOCache();
        }

        /**
         * Retrieves the name of the controller.
         *
         * @return the controller name
         */
        public String getControllerName()
        {
            return controllerName;
        }

        /**
         * Retrieves the maximum number of devices per controller port.
         *
         * @return the max number of devices per port
         */
        public int getMaxDevicesPerPort()
        {
            return maxDevicesPerPort;
        }

        /**
         * Retrieves the lowest usable controller port.
         *
         * @return the port
         */
        public int getLowPort()
        {
            return lowPort;
        }

        /**
         * Retrieves the highest usable controller port.
         *
         * @return the port
         */
        public int getHighPort()
        {
            return highPort;
        }

        /**
         * Retrieves the instance number of the controller in the guest.
         *
         * @return the instance number
         */
        public int getVmInstanceNumber()
        {
            return vmInstanceNumber;
        }

        /**
         * Retrieves the number of currently usable ports.
         *
         * @return the ports number
         */
        public int getNumberOfCurrentlyUsablePorts()
        {
            return numberOfCurrentlyUsablePorts;
        }

        /**
         * Retrieves the controller's connection type.
         *
         * @return the connection type
         */
        public StorageBus getConnectionType()
        {
            return connectionType;
        }

        /**
         * Retrieves the controller type.
         *
         * @return the controller type
         */
        public StorageControllerType getControllerType()
        {
            return controllerType;
        }

        /**
         * Returns whether the host's I/O cache is used.
         *
         * @return <code>true</code> if the host's cache is used or <code>false</code>
         *         otherwise
         */
        public boolean isHostIOCacheUsed()
        {
            return hostIOCacheUsed;
        }

        /**
         * Checks the validity of the settings.
         *
         * @return <code>true</code> if the settings are valid or <code>false</code> .
         *         otherwise
         */
        @Override
        public boolean isValid()
        {
            if(controllerName != null && connectionType != null && controllerType != null)
                return true;
            else
                return false;
        }
    }

    /**
     * This class represents medium attachment settings.
     */
    public class MediumAttachmentSettings implements Serializable, SelfValidating
    {
        private String mediumId;        //the id of the medium
        private String controllerName;  //attached controller name
        private int controllerPort;     //controller port
        private int controllerSlot;     //controller slot
        private DeviceType deviceType;  //device type
        private boolean passthroughEnabled;//denotes whether passthrough is enabled

        /**
         * Constructs a medium attachment object using the specified data.
         *
         * @param attachment a machine's medium attachment
         */
        public MediumAttachmentSettings(IMediumAttachment attachment)
        {
            if(attachment.getMedium() != null)
                this.mediumId = attachment.getMedium().getId();
            else
                this.mediumId = null;
            
            this.controllerName = attachment.getController();
            this.controllerPort = attachment.getPort();
            this.controllerSlot = attachment.getDevice();
            this.deviceType = attachment.getType();
            this.passthroughEnabled = attachment.isPassthrough();
        }

        /**
         * Retrieves the id of the medium associated with this attachment.
         *
         * @return the medium id, if available or <code>null</code> otherwise
         */
        public String getMediumId()
        {
            return mediumId;
        }

        /**
         * Retrieves the name of the controller on which the medium is attached.
         *
         * @return the controller name
         */
        public String getControllerName()
        {
            return controllerName;
        }

        /**
         * Retrieves the controller port on which the medium is attached.
         *
         * @return the controller port
         */
        public int getControllerPort()
        {
            return controllerPort;
        }

        /**
         * Retrieves the controller device slot on which the medium is attached.
         *
         * @return the controller slot
         */
        public int getControllerSlot()
        {
            return controllerSlot;
        }

        /**
         * Retrieves the medium's device type.
         *
         * @return the device type
         */
        public DeviceType getDeviceType()
        {
            return deviceType;
        }

        /**
         * Returns whether the attachment has I/O passthrough enabled.
         *
         * @return <code>true</code> if passthrough is enabled or <code>false</code>
         *         otherwise
         */
        public boolean isPassthroughEnabled()
        {
            return passthroughEnabled;
        }

        /**
         * Checks the validity of the settings.
         *
         * @return <code>true</code> if the settings are valid or <code>false</code>
         *         otherwise
         */
        @Override
        public boolean isValid()
        {
            if(Functions.isControllerPortValid(controllerPort) && Functions.isControllerSlotValid(controllerSlot)
                    && controllerName != null && deviceType != null && (mediumId == null || Functions.isUUIDValid(mediumId)))
                return true;
            else
                return false;
        }
    }
}
